package jnpf.service.impl;

import cn.hutool.core.util.BooleanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import jnpf.base.UserInfo;
import jnpf.base.entity.SignEntity;
import jnpf.base.entity.SystemEntity;
import jnpf.base.model.base.SystemBaeModel;
import jnpf.base.model.button.ButtonModel;
import jnpf.base.model.column.ColumnModel;
import jnpf.base.model.form.ModuleFormModel;
import jnpf.base.model.module.ModuleModel;
import jnpf.base.model.resource.ResourceModel;
import jnpf.base.service.SignService;
import jnpf.base.service.SysconfigService;
import jnpf.base.service.SystemService;
import jnpf.config.ConfigValueUtil;
import jnpf.constant.MsgCode;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.message.entity.MessageTemplateConfigEntity;
import jnpf.message.service.MessageService;
import jnpf.message.service.MessageTemplateConfigService;
import jnpf.model.BaseSystemInfo;
import jnpf.model.UserMenuModel;
import jnpf.portal.constant.PortalConst;
import jnpf.portal.service.PortalDataService;
import jnpf.util.data.DataSourceContextHolder;
import jnpf.database.model.TenantVO;
import jnpf.exception.LoginException;
import jnpf.granter.UserDetailsServiceBuilder;
import jnpf.model.login.*;
import jnpf.permission.constant.PermissionConst;
import jnpf.permission.entity.*;
import jnpf.permission.model.authorize.AuthorizeVO;
import jnpf.permission.service.*;
import jnpf.permissions.PermissionInterfaceImpl;
import jnpf.portal.model.PortalSelectModel;
import jnpf.portal.service.PortalService;
import jnpf.service.LoginService;
import jnpf.util.*;
import jnpf.util.treeutil.ListToTreeUtil;
import jnpf.util.treeutil.SumTree;
import jnpf.util.treeutil.newtreeutil.TreeDotUtils;
import jnpf.util.LoginHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司（https://www.jnpfsoft.com）
 * @date 2021/3/16
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    private ConfigValueUtil configValueUtil;
    @Autowired
    private UserProvider userProvider;
    @Autowired
    private UserService userApi;
    @Autowired
    private UserRelationService userRelationApi;
    @Autowired
    private OrganizeService organizeApi;
    @Autowired
    private PositionService positionApi;
    @Autowired
    private RoleService roleApi;
    @Autowired
    private AuthorizeService authorizeApi;
    @Autowired
    private SysconfigService sysconfigApi;
    @Autowired
    private PortalService portalApi;
    @Autowired
    private PortalDataService portalDataService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private CacheKeyUtil cacheKeyUtil;
    @Autowired
    private OrganizeRelationService organizeRelationApi;
    @Autowired
    private SystemService systemApi;
    @Autowired
    private UserDetailsServiceBuilder userDetailsServiceBuilder;
    @Autowired
    private SignService signService;
    @Autowired
    private MessageTemplateConfigService messageTemplateApi;
    @Autowired
    private MessageService sentMessageApi;



    @Override
    public UserInfo getTenantAccount(UserInfo userInfo) throws LoginException {
        String tenantId = "";
        if (configValueUtil.isMultiTenancy()) {
            String[] tenantAccount = userInfo.getUserAccount().split("\\@");
            tenantId = tenantAccount.length == 1 ? userInfo.getUserAccount() : tenantAccount[0];
            userInfo.setUserAccount(tenantAccount.length == 1 ? "admin" : tenantAccount[1]);
            if (tenantAccount.length > 2 || StringUtil.isEmpty(tenantId) || StringUtil.isEmpty(userInfo.getUserAccount())) {
                throw new LoginException(MsgCode.LOG102.get());
            }
            TenantVO tenantVO = TenantDataSourceUtil.getRemoteTenantInfo(tenantId);
            TenantDataSourceUtil.switchTenant(tenantId, tenantVO);
            //切换成租户库
            userInfo.setTenantId(tenantId);
            userInfo.setTenantDbConnectionString(DataSourceContextHolder.getDatasourceName());
            userInfo.setAssignDataSource(DataSourceContextHolder.isAssignDataSource());
            //查库测试
            BaseSystemInfo baseSystemInfo = null;
            try {
                baseSystemInfo = getBaseSystemConfig(userInfo.getTenantId(), userInfo.getTenantDbConnectionString(), userInfo.isAssignDataSource());
            }catch (Exception e) {
                log.error("登录获取系统配置失败: {}", e.getMessage());
            }
            if(baseSystemInfo == null || baseSystemInfo.getSingleLogin() == null) {
                if (configValueUtil.getMultiTenancyUrl().contains("https")) {
                    throw new LoginException("租户登录失败，请用手机验证码登录");
                } else {
                    throw new LoginException("数据库异常，请联系管理员处理");
                }
            }
        }
        return userInfo;
    }

    @Override
    public UserInfo userInfo(UserInfo userInfo, BaseSystemInfo sysConfigInfo) throws LoginException {
        //获取账号信息
        UserEntity userEntity = LoginHolder.getUserEntity();
        if(userEntity == null){
            userEntity = userDetailsServiceBuilder.getUserDetailService(userInfo.getUserDetailKey()).loadUserEntity(userInfo);
            LoginHolder.setUserEntity(userEntity);
        }

        checkUser(userEntity, userInfo, sysConfigInfo);

        userInfo.setIsAdministrator(BooleanUtil.toBoolean(String.valueOf(userEntity.getIsAdministrator())));
        userInfo.setUserId(userEntity.getId());
        userInfo.setUserAccount(userEntity.getAccount());
        userInfo.setUserName(userEntity.getRealName());
        userInfo.setUserIcon(userEntity.getHeadIcon());
        userInfo.setTheme(userEntity.getTheme());
        userInfo.setOrganizeId(userEntity.getOrganizeId());
        userInfo.setPortalId(userEntity.getPortalId());
        userInfo.setIsAdministrator(BooleanUtil.toBoolean(String.valueOf((userEntity.getIsAdministrator()))));

        // 添加过期时间
        String time = sysConfigInfo.getTokenTimeout();
        if (StringUtil.isNotEmpty(time)) {
            Integer minu = Integer.valueOf(time);
            userInfo.setOverdueTime(DateUtil.dateAddMinutes(null, minu));
            userInfo.setTokenTimeout(minu);
        }

        userInfo.setLoginIpAddress(IpUtil.getIpAddr());
        userInfo.setLoginTime(DateUtil.getmmNow());
        userInfo.setLoginPlatForm(ServletUtil.getUserAgent());
        userInfo.setPrevLoginTime(userEntity.getPrevLogTime());
        userInfo.setPrevLoginIpAddress(userEntity.getPrevLogIp());
        userInfo.setPrevLoginIpAddressName(IpUtil.getIpCity(userEntity.getPrevLogIp()));
        // 生成id
        String token = RandomUtil.uuId();
        userInfo.setId(cacheKeyUtil.getLoginToken(userInfo.getTenantId()) + token);

        createUserOnline(userInfo);
        return userInfo;
    }

    @Override
    public void updatePasswordMessage(){
        UserInfo userInfo = userProvider.get();
        UserEntity userEntity = userApi.getInfo(userInfo.getUserId());
        BaseSystemInfo baseSystemInfo = sysconfigApi.getSysInfo();
        if(baseSystemInfo.getPasswordIsUpdatedRegularly()==1){
            Date changePasswordDate = userEntity.getCreatorTime();
            if(userEntity.getChangePasswordDate()!=null){
                changePasswordDate = userEntity.getChangePasswordDate();
            }
            //当前时间
            Date nowDate = DateUtil.getNowDate();
            //更新周期
            Integer updateCycle = baseSystemInfo.getUpdateCycle();
            //提前N天提醒
            Integer updateInAdvance = baseSystemInfo.getUpdateInAdvance();
            Integer day = DateUtil.getDiffDays(changePasswordDate,nowDate);
            if(day>=(updateCycle-updateInAdvance)){
                MessageTemplateConfigEntity entity = messageTemplateApi.getInfoByEnCode("XTXXTX001","1");
                if(entity != null) {
                    List<String> toUserIds = new ArrayList<>();
                    toUserIds.add(userInfo.getUserId());
                    sentMessageApi.sentMessage(toUserIds, entity.getTitle(), entity.getContent(), userInfo, Integer.parseInt(entity.getMessageSource()), Integer.parseInt(entity.getMessageType()));
                }
            }
        }
    }

    /**
     * 创建用户在线信息
     * @param userInfo
     */
    private void createUserOnline(UserInfo userInfo){
        String userId = userInfo.getUserId();
//        long time= DateUtil.getTime(userInfo.getOverdueTime()) - DateUtil.getTime(new Date());

        String authorize = String.valueOf(redisUtil.getString(cacheKeyUtil.getUserAuthorize() + userId));
//        String loginOnlineKey=cacheKeyUtil.getLoginOnline() + userId;
        redisUtil.remove(authorize);
        //记录Token
//        redisUtil.insert(userInfo.getId(), userInfo,time);
        //记录在线
        if (ServletUtil.getIsMobileDevice()) {
//            redisUtil.insert(cacheKeyUtil.getMobileLoginOnline() + userId, userInfo.getId(), time);
            //记录移动设备CID,用于消息推送
            if (ServletUtil.getHeader("clientId") != null) {
                String clientId = ServletUtil.getHeader("clientId");
                Map<String, String> map = new HashMap<>(16);
                map.put(userInfo.getUserId(), clientId);
                redisUtil.insert(cacheKeyUtil.getMobileDeviceList(), map);
            }
        } else {
//            redisUtil.insert(loginOnlineKey, userInfo.getId(), time);
        }
    }

    private UserCommonInfoVO data(UserInfo userInfo) {
        //公司Id
        List<OrganizeEntity> list = organizeApi.getList();
        UserEntity userEntity = userApi.getInfo(userInfo.getUserId());
        userInfo.setManagerId(userInfo.getManagerId());
        boolean b = userInfo.getIsAdministrator();
        if (StringUtil.isEmpty(userEntity.getSystemId())) {
            SystemEntity systemEntity = systemApi.getMainSystem();
            userInfo.setSystemId(systemEntity.getId());
            userEntity.setSystemId(systemEntity.getId());
        }
        this.userInfo(userInfo, userInfo.getUserId(), b, userEntity);
        userInfo.setSubOrganizeIds(this.getSubOrganizeIds(list, userInfo.getOrganizeId(), b));
        List<String> subordinateIdsList = userApi.getListByManagerId(userInfo.getUserId(), null).stream().map(UserEntity::getId).collect(Collectors.toList());
        userInfo.setSubordinateIds(subordinateIdsList);
        userInfo.setLoginTime(DateUtil.getmmNow());
        userInfo.setLoginPlatForm(ServletUtil.getUserAgent());
//        if (StringUtil.isNotEmpty(userInfo.getId())) {
//            redisUtil.insert(userInfo.getId(), userInfo, DateUtil.getTime(userInfo.getOverdueTime()) - DateUtil.getTime(new Date()));
//        }
        BaseSystemInfo baseSystemInfo = sysconfigApi.getSysInfo();
        UserCommonInfoVO infoVO = JsonUtil.getJsonToBean(genUserInfo(userInfo, baseSystemInfo), UserCommonInfoVO.class);
        // 角色数组
        infoVO.setRoleIds(userInfo.getRoleIds());
        //最后一次修改密码时间
        infoVO.setChangePasswordDate(userEntity.getChangePasswordDate());
        // 角色名称
        StringBuilder roleName = new StringBuilder();
        for (RoleEntity entity : roleApi.getListByIds(userInfo.getRoleIds())) {
            roleName.append("," + entity.getFullName());
        }
        if (roleName.length() > 0) {
            infoVO.setRoleName(roleName.toString().replaceFirst(",", ""));
        }
        // 主管
        UserEntity info = userApi.getInfo(userEntity.getManagerId());
        if (info != null) {
            infoVO.setManager(info.getRealName() + "/" + info.getAccount());
        }
        // 手机
        infoVO.setMobilePhone(userEntity.getMobilePhone());
        // 邮箱
        infoVO.setEmail(userEntity.getEmail());
        // 生日
        infoVO.setBirthday(userEntity.getBirthday() != null ? userEntity.getBirthday().getTime() : null);
        // 姓名
        infoVO.setUserName(userEntity.getRealName());
        //组织
        OrganizeEntity organizeEntity = organizeApi.getInfo(userInfo.getOrganizeId());
        String organizeName = null;
        String departmentId = null;
        String departmentName = null;
        List<String> departmentIdList = null;
        String organizeId = null;
        if (organizeEntity != null) {
            if (PermissionConst.DEPARTMENT.equals(organizeEntity.getCategory())) {
                organizeName = organizeEntity.getFullName();
                organizeId = organizeEntity.getId();
            }
            if (StringUtil.isNotEmpty(organizeEntity.getOrganizeIdTree())) {
                String[] split = organizeEntity.getOrganizeIdTree().split(",");
                departmentId = split.length > 0 ? split[split.length - 1] : "";
                departmentIdList = split.length > 0 ? Arrays.asList(split) : new ArrayList<String>();
                departmentName = organizeApi.getFullNameByOrgIdTree(organizeEntity.getOrganizeIdTree(), "/");
            }
        }
        infoVO.setOrganizeName(departmentName);
        infoVO.setOrganizeId(departmentId);
        infoVO.setOrganizeIdList(departmentIdList == null?new ArrayList<String>():departmentIdList);
        // 部门id
        infoVO.setDepartmentId(organizeId);
        // 部门名称
        infoVO.setDepartmentName(organizeName);
        infoVO.setIsAdministrator(BooleanUtil.toBoolean(String.valueOf(userEntity.getIsAdministrator())));

        return infoVO;
    }

    /**
     * 得到系统模型
     *
     * @param userEntity
     */
    private void getSystemVO(UserInfo userInfo, UserEntity userEntity, List<UserSystemVO> systemIds) {
        List<String> roleIds = userInfo.getRoleIds();
        List<SystemBaeModel> systemList = new ArrayList<>(16);
        if (!userInfo.getIsAdministrator()) {
            if (roleIds != null && roleIds.size() > 0) {
                systemList = authorizeApi.findSystem(roleIds);
            }
        } else {
            List<SystemEntity> systemLists = systemApi.getList(null, false);
            systemList = JsonUtil.getJsonToList(systemLists, SystemBaeModel.class);
        }
        SystemEntity entity = systemApi.getInfo(userInfo.getSystemId());
        if (entity != null) {
            SystemBaeModel jsonToBean = JsonUtil.getJsonToBean(entity, SystemBaeModel.class);
            SystemBaeModel systemBaeModel = systemList.stream().filter(t -> t.getId().equals(jsonToBean.getId())).findFirst().orElse(null);
            if (systemBaeModel == null) {
                systemList.add(jsonToBean);
            }
        }
        List<String> collect = systemList.stream().map(SystemBaeModel::getId).collect(Collectors.toList());
        if (collect.size() > 0) {
            List<SystemEntity> list1 = systemApi.getListByIds(collect);
            list1.forEach(t -> {
                UserSystemVO userSystemVO = new UserSystemVO();
                userSystemVO.setId(t.getId());
                userSystemVO.setName(t.getFullName());
                userSystemVO.setIcon(t.getIcon());
                String systemId = userEntity.getSystemId();
                if (StringUtil.isEmpty(systemId)) {
                    SystemEntity mainSystem = systemApi.getMainSystem();
                    if (mainSystem.getId().equals(t.getId())) {
                        userSystemVO.setCurrentSystem(true);
                        userInfo.setSystemId(mainSystem.getId());
                    }
                } else if (t.getId().equals(userEntity.getSystemId())) {
                    userSystemVO.setCurrentSystem(true);
                    userInfo.setSystemId(t.getId());
                }
                systemIds.add(userSystemVO);
            });
        }
    }

    /**
     * 递归找他的上级
     */
    public void getOrganizeName(List<OrganizeEntity> OrganizeList, String organizeId) throws Exception {
        List<OrganizeEntity> OrganizeList2 = OrganizeList.stream().filter(t -> organizeId.equals(t.getId())).collect(Collectors.toList());
        if (OrganizeList2.size() > 0) {
            for (OrganizeEntity organizeEntity : OrganizeList2) {
                if (organizeEntity.getParentId().equals("-1")) {
                    //父级为-1时候退出
                    throw new Exception(JSON.toJSONString(organizeEntity));
                }
            }
            for (OrganizeEntity orgSub : OrganizeList2) {
                getOrganizeName(OrganizeList, orgSub.getParentId());
            }
        }
    }

    public UserEntity checkUser(UserEntity userEntity, UserInfo userInfo, BaseSystemInfo sysConfigInfo) throws LoginException {
        if (userEntity == null) {
            throw new LoginException(MsgCode.LOG003.get());
        }
        //判断是否组织、岗位、角色、部门主管是否为空，为空则抛出异常
        //判断是否为管理员，是否为Admin(Admin为最高账号，不受限制)
        if (!"admin".equals(userEntity.getAccount()) || userEntity.getIsAdministrator() != 1) {
            //组织id为空则直接抛出异常
            if (StringUtil.isEmpty(userEntity.getOrganizeId())) {
                throw new LoginException(MsgCode.LOG004.get());
            }
            // 岗位id为空则直接抛出异常
//            if (StringUtil.isEmpty(userEntity.getPositionId())) {
//                throw new LoginException("账号异常，请联系管理员修改所属岗位信息");
//            }
//            //角色id为空则直接抛出异常
//            if (StringUtil.isEmpty(userEntity.getRoleId())) {
//                throw new LoginException("账号异常，请联系管理员修改角色信息");
//            }
//            //主管id为空则直接抛出异常
//            if (StringUtil.isEmpty(userEntity.getManagerId())) {
//                throw new LoginException("账号异常，请联系管理员修改主管信息");
//            }
        }
        if (userEntity.getIsAdministrator() == 0) {
            if (userEntity.getEnabledMark() == null) {
                throw new LoginException(MsgCode.LOG005.get());
            }
            if (userEntity.getEnabledMark() == 0) {
                throw new LoginException(MsgCode.LOG006.get());
            }
        }
        if (userEntity.getDeleteMark() != null && userEntity.getDeleteMark() == 1) {
            throw new LoginException(MsgCode.LOG007.get());
        }
        //安全验证
        String ipAddr = IpUtil.getIpAddr();
        userInfo.setLoginIpAddress(IpUtil.getIpAddr());
        // 判断白名单
        if (!"admin".equals(userEntity.getAccount()) && "1".equals(sysConfigInfo.getWhitelistSwitch())) {
            List<String> ipList = Arrays.asList(sysConfigInfo.getWhitelistIp().split(","));
            if (!ipList.contains(ipAddr)) {
                throw new LoginException(MsgCode.LOG010.get());
            }
        }
        //判断用户所属的角色是否被禁用
        if (userEntity.getIsAdministrator() != 1) {
            if (userEntity.getIsAdministrator() == 0) {
                List<RoleEntity> userAllRole = roleApi.getListByUserId(userEntity.getId());
                boolean permissionFlag = false;
                for (RoleEntity role : userAllRole) {
                    if (role != null && role.getEnabledMark() != null && role.getEnabledMark() != 0) {
                        permissionFlag = true;
                        break;
                    }
                }
                if(!permissionFlag){
                    throw new LoginException(MsgCode.LOG011.get());
                }
            } else {
                throw new LoginException(MsgCode.LOG011.get());
            }
        }
        // 判断当前账号是否被锁定
        Integer lockMark = userEntity.getEnabledMark();
        if (Objects.nonNull(lockMark) && lockMark == 2) {
            // 获取解锁时间
            Date unlockTime = userEntity.getUnlockTime();
            // 账号锁定
            if (sysConfigInfo.getLockType() == 1 || Objects.isNull(unlockTime)) {
                throw new LoginException(MsgCode.LOG012.get());
            }
            // 延迟登陆锁定
            long millis = System.currentTimeMillis();
            // 系统设置的错误次数
            int passwordErrorsNumber = sysConfigInfo.getPasswordErrorsNumber() != null ? sysConfigInfo.getPasswordErrorsNumber() : 0;
            // 用户登录错误次数
            int logErrorCount = userEntity.getLogErrorCount() != null ? userEntity.getLogErrorCount() : 0;
            if (unlockTime.getTime() > millis) {
                // 转成分钟
                int time = (int) ((unlockTime.getTime() - millis) / (1000 * 60));
                throw new LoginException(MsgCode.LOG013.get().replace("{time}", Integer.toString(time + 1)));
            } else if (unlockTime.getTime() < millis && logErrorCount >= passwordErrorsNumber){
                // 已经接触错误时间锁定的话就重置错误次数
                userEntity.setLogErrorCount(0);
                userEntity.setEnabledMark(1);
                userApi.updateById(userEntity);
            }
        }
        return userEntity;
    }

    /**
     * 获取用户登陆信息
     *
     * @return
     */
    @Override
    public PcUserVO getCurrentUser(String type) {
        UserInfo userInfo = userProvider.get();
        UserCommonInfoVO infoVO = this.data(userInfo);
        AuthorizeVO authorizeModel = authorizeApi.getAuthorize(false);
        BaseSystemInfo sysInfo = sysconfigApi.getSysInfo();
        // 获取菜单权限
        List<ModuleModel> moduleList = authorizeModel.getModuleList();
        moduleList = moduleList.stream().filter(t -> t.getSystemId() != null && t.getSystemId().equals(userInfo.getSystemId())).collect(Collectors.toList());
        // 判断是否需要切换系统
        if (moduleList.size() > 0) {
            String systemId = moduleList.get(0).getSystemId();
            SystemEntity systemEntity = systemApi.getInfo(systemId);
            if (systemEntity.getEnabledMark() == 0) {
                moduleList = new ArrayList<>();
            }
        }
        // 判断是否为Web
        List<ModuleModel> menuList = moduleList.stream().filter(t -> type.equals(t.getCategory())).sorted(Comparator.comparing(ModuleModel::getSortCode)).collect(Collectors.toList());
        // 判断是否有权限
        if (menuList.size() == 0) {
            // 得到系统列表
            List<SystemBaeModel> systemBaeModels = authorizeApi.systemListByRoleIds(userInfo.getRoleIds());
            List<SystemEntity> mainSystemList = systemApi.getMainSys(systemBaeModels.stream().map(SystemBaeModel::getId).collect(Collectors.toList()));
            if (mainSystemList.size() > 0) {
                // 有主系统，取主系统
                for (SystemEntity systemEntity : mainSystemList) {
                    menuList = authorizeModel.getModuleList().stream().filter(t -> systemEntity.getId().equals(t.getSystemId()) && type.equals(t.getCategory())).collect(Collectors.toList());
                    if (menuList.size() > 0) {
                        break;
                    }
                }
            }
            if (menuList.size() == 0) {
                // 没有主系统随机取一个
                for (SystemBaeModel systemBaeModel : systemBaeModels) {
                    menuList = authorizeModel.getModuleList().stream().filter(t -> t.getSystemId().equals(systemBaeModel.getId()) && type.equals(t.getCategory())).collect(Collectors.toList());
                    if (menuList.size() > 0) {
                        break;
                    }
                }
            }
        }
        // 菜单id不为空则更改默认系统id
        if (menuList.size() > 0) {
            String systemId = menuList.get(0) != null ? menuList.get(0).getSystemId() : "";
            UserEntity userEntity = userApi.getInfo(userInfo.getUserId());
            if (userEntity != null) {
                userEntity.setSystemId(systemId);
                userApi.updateById(userEntity);
                userInfo.setSystemId(systemId);

                // 设置系统模型
                List<UserSystemVO> systemIds = new ArrayList<>(16);
                getSystemVO(userInfo, userEntity, systemIds);
                infoVO.setSystemIds(systemIds);
            }
        }
        if (StringUtil.isNotEmpty(userInfo.getId())) {
            //redisUtil.insert(userInfo.getId(), userInfo, DateUtil.getTime(userInfo.getOverdueTime()) - DateUtil.getTime(new Date()));
            UserProvider.setLoginUser(userInfo);
            UserProvider.setLocalLoginUser(userInfo);
        }
        //返回前台tree的list
        List<UserMenuModel> menu = JsonUtil.getJsonToList(menuList, UserMenuModel.class);
        List<SumTree<UserMenuModel>> menus = TreeDotUtils.convertListToTreeDot(menu, "-1");
        //返回前台tree的list
        List<MenuTreeVO> list = JsonUtil.getJsonToList(menus, MenuTreeVO.class);
        //岗位
        List<String> posiList = Arrays.asList(userInfo.getPositionIds());
        List<PositionEntity> positionList = positionApi.getPositionName(posiList);
        List<UserPositionVO> positionVO = new ArrayList<>();
        for (PositionEntity positionEntity : positionList) {
            UserPositionVO userPositionVO = new UserPositionVO();
            userPositionVO.setName(positionEntity.getFullName());
            userPositionVO.setId(positionEntity.getId());
            positionVO.add(userPositionVO);
        }
        List<PermissionModel> models = new ArrayList<>();
        for (ModuleModel moduleModel : menuList) {
            PermissionModel model = new PermissionModel();
            model.setModelId(moduleModel.getId());
            model.setModuleName(moduleModel.getFullName());
            List<ButtonModel> buttonModels = authorizeModel.getButtonList().stream().filter(t -> moduleModel.getId().equals(t.getModuleId())).collect(Collectors.toList());
            List<ColumnModel> columnModels = authorizeModel.getColumnList().stream().filter(t -> moduleModel.getId().equals(t.getModuleId())).collect(Collectors.toList());
            List<ResourceModel> resourceModels = authorizeModel.getResourceList().stream().filter(t -> moduleModel.getId().equals(t.getModuleId())).collect(Collectors.toList());
            List<ModuleFormModel> moduleFormModels = authorizeModel.getFormsList().stream().filter(t -> moduleModel.getId().equals(t.getModuleId())).collect(Collectors.toList());
            model.setButton(JsonUtil.getJsonToList(buttonModels, PermissionVO.class));
            model.setColumn(JsonUtil.getJsonToList(columnModels, PermissionVO.class));
            model.setResource(JsonUtil.getJsonToList(resourceModels, PermissionVO.class));
            model.setForm(JsonUtil.getJsonToList(moduleFormModels, PermissionVO.class));
            if (moduleModel.getType() != 1) {
                models.add(model);
            }
        }
        //初始化接口权限
        if(configValueUtil.isEnablePreAuth()) {
            initSecurityAuthorities(authorizeModel, userInfo, sysInfo);
        }

        UserEntity info = userApi.getInfo(userInfo.getUserId());
        if (info != null) {
            // 门户Web
            try{
                String defaultPortalId = portalDataService.getCurrentDefault(PortalConst.WEB);
                infoVO.setPortalId(defaultPortalId);
            }catch (Exception e){
                infoVO.setPortalId("");
                e.printStackTrace();
            }
            // 门户App
            try{
                String defaultAppPortalId = portalDataService.getCurrentDefault(PortalConst.APP);
                infoVO.setAppPortalId(defaultAppPortalId);
            }catch (Exception e){
                infoVO.setAppPortalId("");
                e.printStackTrace();
            }
            // 岗位
            PositionEntity positionEntity = positionApi.getInfo(info.getPositionId());
            infoVO.setPositionId(positionEntity != null ? positionEntity.getId() : "");
            infoVO.setPositionName(positionEntity != null ? positionEntity.getFullName() : "");
            // 获取签名信息
            SignEntity signEntity = signService.getDefaultByUserId(info.getId());
            infoVO.setSignImg(signEntity != null ? signEntity.getSignImg() : "");
        }
        infoVO.setPositionIds(positionVO);

        SystemInfo jsonToBean = JsonUtil.getJsonToBean(sysInfo, SystemInfo.class);

        // 构建菜单树
        List<AllMenuSelectVO> menuSelectVOS = buildModule(authorizeModel.getSystemList(), authorizeModel.getModuleList(), type);

        PcUserVO userVO = new PcUserVO(list, models, infoVO, jsonToBean, menuSelectVOS);
        userVO.setPermissionList(models);
        userVO.getUserInfo().setHeadIcon(UploaderUtil.uploaderImg(userInfo.getUserIcon()));
        return userVO;
    }

    @Override
    public BaseSystemInfo getBaseSystemConfig(String tenantId, String tenantDb, boolean isAssignDataSource) {
        if(tenantId != null && tenantDb != null){
            DataSourceContextHolder.setDatasource(tenantId, tenantDb, isAssignDataSource);
        }
        return sysconfigApi.getSysInfo();
    }

    private List<AllMenuSelectVO> buildModule(List<SystemBaeModel> systemList, List<ModuleModel> moduleList, String type) {
        // 获取所有菜单树（区分Web、APP）
        moduleList = moduleList.stream().filter(t -> type.equals(t.getCategory())).collect(Collectors.toList());
        List<AllUserMenuModel> list = JsonUtil.getJsonToList(moduleList, AllUserMenuModel.class);
        list.forEach(t -> {
            if ("-1".equals(t.getParentId())) {
                t.setParentId(t.getSystemId());
            }
        });
        List<AllUserMenuModel> jsonToList = JsonUtil.getJsonToList(systemList, AllUserMenuModel.class);
        jsonToList.forEach(t -> {
            t.setType(0);
            t.setParentId("-1");
        });
        list.addAll(jsonToList);
        List<SumTree<AllUserMenuModel>> menuList = TreeDotUtils.convertListToTreeDotFilter(list);
        List<AllMenuSelectVO> menuvo = JsonUtil.getJsonToList(menuList, AllMenuSelectVO.class);
        return menuvo;
    }

    /**
     * 初始化接口鉴权用的账号权限
     * 本接口插入权限缓存， SaInterfaceImpl中框架鉴权时动态调用获取权限列表
     * @param authorizeModel
     * @param userInfo
     */
    private void initSecurityAuthorities(AuthorizeVO authorizeModel, UserInfo userInfo, BaseSystemInfo systemInfo){
        //接口权限
        Set<String> authorityList = new HashSet<>();
        Map<String, ModuleModel> moduleModelMap = authorizeModel.getModuleList().stream().filter(m->{
            //添加菜单权限
            authorityList.add(m.getEnCode());
            return true;
        }).collect(Collectors.toMap(m->m.getId(), m->m));
        for (ModuleModel moduleModel : authorizeModel.getModuleList()) {
            String permissionKey = moduleModel.getEnCode();
            authorityList.add(permissionKey);
            //功能菜单
            if(moduleModel.getType() == 3){
                JSONObject propertyJSON = JSONObject.parseObject(Optional.of(moduleModel.getPropertyJson()).orElse("{}"));
                //{"iconBackgroundColor":"","isTree":0,"moduleId":"395851986114733317"}
                String moduleId = propertyJSON.getString("moduleId");
                if(!StringUtil.isEmpty(moduleId)){
                    authorityList.add(moduleId);
                }
            }
        }

        authorizeModel.getButtonList().stream().forEach(t -> {
            ModuleModel m = moduleModelMap.get(t.getModuleId());
            if(m != null){
                authorityList.add(m.getEnCode() + "::" + t.getEnCode());
            }
        });
        authorizeModel.getColumnList().stream().forEach(t -> {
            ModuleModel m = moduleModelMap.get(t.getModuleId());
            if(m != null){
                authorityList.add(m.getEnCode() + "::" + t.getEnCode());
            }
        });
        authorizeModel.getFormsList().stream().forEach(t -> {
            ModuleModel m = moduleModelMap.get(t.getModuleId());
            if(m != null){
                authorityList.add(m.getEnCode() + "::" + t.getEnCode());
            }
        });

        //管理员都是用同一个缓存, 普通账号使用账号名,
        //权限列表：authorize_:租户_authorize_authorize_(admin|账号)
        //角色列表：authorize_:租户_authorize_role_(admin|账号)
        String authorityKey = CacheKeyUtil.USERAUTHORIZE + ":" + cacheKeyUtil.getUserAuthorize() + "authority_" + (userInfo.getIsAdministrator()?"admin":userInfo.getUserAccount());
        String account = userInfo.getIsAdministrator()? PermissionInterfaceImpl.ADMIN_KEY :userInfo.getUserId();
        PermissionInterfaceImpl.setAuthorityList(account, authorityList, systemInfo);
        if (userInfo.getRoleIds() != null && !userInfo.getRoleIds().isEmpty() || userInfo.getIsAdministrator()) {
            String rolesKey = CacheKeyUtil.USERAUTHORIZE + ":" + cacheKeyUtil.getUserAuthorize() + "role_" + (userInfo.getIsAdministrator()?"admin":userInfo.getUserAccount());
            List<RoleEntity> roles;
            if(userInfo.getIsAdministrator()){
                roles = roleApi.getList();
            }else{
                roles = roleApi.getListByIds(userInfo.getRoleIds());
            }
            Set<String> roleAuthorityList = roles.stream().filter(r->r.getEnabledMark().equals(1)).map(r -> "ROLE_" + r.getEnCode()).collect(Collectors.toSet());
            PermissionInterfaceImpl.setRoleList(account, roleAuthorityList, systemInfo);
        }
    }

    /**
     * 获取下属机构
     *
     * @param data
     * @param organizeId
     * @param isAdmin
     * @return
     */
    private String[] getSubOrganizeIds(List<OrganizeEntity> data, String organizeId, boolean isAdmin) {
        if (!isAdmin) {
            data = JsonUtil.getJsonToList(ListToTreeUtil.treeWhere(organizeId, data), OrganizeEntity.class);
        }
        List<String> list = data.stream().map(t -> t.getId()).collect(Collectors.toList());
        return list.toArray(new String[list.size()]);
    }

    /**
     * 赋值
     *
     * @param userInfo
     * @param userId
     * @param isAdmin
     */
    private void userInfo(UserInfo userInfo, String userId, boolean isAdmin, UserEntity userEntity) {
        // 得到用户和组织的关系
        List<UserRelationEntity> data = userRelationApi.getListByUserIdAndObjType(userId, PermissionConst.ORGANIZE);
        // 组织id
        String organizeId = "";
        String departmentId = "";
        List<String> roleId = new ArrayList<>();
        // 判断当前组织是否有权限
        if(!organizeRelationApi.checkBasePermission(userEntity.getId(), userEntity.getOrganizeId())) {
            if (data.size() > 0) {
                // 得到组织id
                organizeId = organizeRelationApi.autoGetMajorOrganizeId(userId, data.stream().map(UserRelationEntity::getObjectId).collect(Collectors.toList()), userEntity.getOrganizeId());
            }
        } else {
            // 如果有权限
            organizeId = userEntity.getOrganizeId();
            if (isAdmin) {
                roleId = data.stream().map(t -> t.getObjectId()).collect(Collectors.toList());
            }
        }
        // 获取用户的角色
        List<UserRelationEntity> listByObjectId = userRelationApi.getListByUserId(userInfo.getUserId(), PermissionConst.ROLE);
        // 判断哪个角色是当前组织下的
        List<String> collect = listByObjectId.stream().map(UserRelationEntity::getObjectId).collect(Collectors.toList());
        // 如果有全局的角色则先赋值给权限集合
        for (String roleIds : collect) {
            // 得到角色
            RoleEntity info = roleApi.getInfo(roleIds);
            if (info != null && "1".equals(String.valueOf(info.getGlobalMark()))) {
                roleId.add(info.getId());
                continue;
            }
            // 判断哪些角色是当前组织的
            Boolean exist = organizeRelationApi.existByRoleIdAndOrgId(roleIds, organizeId);
            if (exist) {
                roleId.add(roleIds);
            }
        }
        // 赋值岗位
        List<String> positionList = data.stream().filter(m -> "Position".equals(m.getObjectType())).map(t -> t.getObjectId()).collect(Collectors.toList());
        Set<String> id = new LinkedHashSet<>();
        String[] position = StringUtil.isNotEmpty(userEntity.getPositionId()) ? userEntity.getPositionId().split(",") : new String[]{};
        List<String> positions = positionList.stream().filter(t -> Arrays.asList(position).contains(t)).collect(Collectors.toList());
        id.addAll(positions);
        id.addAll(positionList);
        String[] positionId = id.toArray(new String[id.size()]);
        userInfo.setOrganizeId(organizeId);
        userInfo.setDepartmentId(departmentId);
        userInfo.setRoleIds(roleId);
        userInfo.setPositionIds(positionId);
        // 处理userInfo
        userInfo.setSystemId(userEntity.getSystemId());
        // 修改用户信息
        userEntity.setOrganizeId(organizeId);
        userEntity.setPositionId(organizeRelationApi.autoGetMajorPositionId(userId, organizeId, userEntity.getPositionId()));
        userApi.updateById(userEntity);
    }


    /**
     * 登录信息
     *
     * @param userInfo   回话信息
     * @param systemInfo 系统信息
     * @return
     */
    private Map<String, Object> genUserInfo(UserInfo userInfo, BaseSystemInfo systemInfo) {
        Map<String, Object> dictionary = new HashMap<>(16);
        dictionary.put("userId", userInfo.getUserId());
        dictionary.put("userAccount", userInfo.getUserAccount());
        dictionary.put("userName", userInfo.getUserName());
        dictionary.put("icon", userInfo.getUserIcon());
        dictionary.put("portalId", userInfo.getPortalId());
        dictionary.put("gender", userInfo.getUserGender());
        dictionary.put("organizeId", userInfo.getOrganizeId());
        dictionary.put("prevLogin", systemInfo.getLastLoginTimeSwitch() == 1 ? 1 : 0);
        dictionary.put("prevLoginTime", userInfo.getPrevLoginTime());
        dictionary.put("prevLoginIPAddress", userInfo.getPrevLoginIpAddress());
        dictionary.put("prevLoginIPAddressName", userInfo.getPrevLoginIpAddressName());
        dictionary.put("serviceDirectory", configValueUtil.getServiceDirectoryPath());
        dictionary.put("webDirectory", configValueUtil.getCodeAreasName());
        dictionary.put("isAdministrator", userInfo.getIsAdministrator());
        return dictionary;
    }

}
